package io.renren.modules.mvs.controller;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.renren.common.annotation.SysLog;
import io.renren.common.exception.RRException;
import io.renren.common.utils.PageUtils;
import io.renren.common.utils.R;
import io.renren.modules.mvs.dto.ViolationDto;
import io.renren.modules.mvs.easyExcel.ViolationData;
import io.renren.modules.mvs.easyExcel.ViolationDataListener;
import io.renren.modules.mvs.entity.TicketEntity;
import io.renren.modules.mvs.entity.VehicleEntity;
import io.renren.modules.mvs.entity.ViolationEntity;
import io.renren.modules.mvs.entity.ViolationTypeEntity;
import io.renren.modules.mvs.service.TicketService;
import io.renren.modules.mvs.service.VehicleService;
import io.renren.modules.mvs.service.ViolationService;
import io.renren.modules.mvs.service.ViolationTypeService;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

import static io.renren.common.utils.Constant.UNPROCESSED;


/**
 * 违章记录表
 *
 * @author chenshun
 * @email sunlightcs@gmail.com
 * @date 2025-03-30 17:08:24
 */
@RestController
@RequestMapping("mvs/violation")
@Log4j2
public class
ViolationController {
    @Autowired
    private ViolationService violationService;
    @Autowired
    private VehicleService vehicleService;
    @Autowired
    private TicketService ticketService;
    @Autowired
    private ViolationTypeService violationTypeService;

    /**
     * 列表
     */
    @GetMapping("/list")
    @RequiresPermissions("mvs:violation:list")
    public R list(@RequestParam Map<String, Object> params) {
        PageUtils page = violationService.queryPage(params);

        return R.ok().put("page", page);
    }


    /**
     * 信息
     */
    @GetMapping("/info/{id}")
    @RequiresPermissions("mvs:violation:info")
    public R info(@PathVariable("id") Long id) {
        ViolationEntity violation = violationService.getById(id);
        return R.ok().put("violation", violation);
    }

    /**
     * dto信息
     */
    @GetMapping("/{id}")
    @RequiresPermissions("mvs:violation:info")
    public R detailInfo(@PathVariable("id") Long id) {
        ViolationDto violation = violationService.getDetailInfoById(id);
        return R.ok().put("violation", violation);
    }

    /**
     * 保存
     */
    @SysLog("新增违章记录")
    @PostMapping("/save")
    @RequiresPermissions("mvs:violation:save")
    public R save(@RequestBody ViolationEntity violation) {
        VehicleEntity vehicle = vehicleService.getById(violation.getVehicleId());
        if (!checkViolationInfo(violation, vehicle)) {
            return R.error("违章记录信息存在错误");
        }
        // TODO 时间范围检查重复插入
        // 用户id
        violation.setUserId(vehicle.getUserId());
        // 缴费截止时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(violation.getViolationTime());
        calendar.add(Calendar.DAY_OF_YEAR, 15);
        violation.setViolationDeadline(calendar.getTime());
        // 违章记录状态
        violation.setViolationStatus(UNPROCESSED);
        violation.setCreateTime(new Date());
        violationService.saveViolation(violation);
        return R.ok();
    }

    private boolean checkViolationInfo(ViolationEntity violation, VehicleEntity vehicle) {
        if (violation.getViolationTime().after(new Date()) || vehicle == null) {
            return false;
        }
        Integer count = violationTypeService
                .lambdaQuery().eq(ViolationTypeEntity::getId, violation.getViolationTypeId()).count();
        return count != 0;
    }

    /**
     * 修改
     */
    @SysLog("修改违章记录")
    @PutMapping("/update")
    @RequiresPermissions("mvs:violation:update")
    public R update(@RequestBody ViolationEntity violation) {
        // 缴费截止时间
        /*Calendar calendar = Calendar.getInstance();
        calendar.setTime(violation.getViolationTime());
        calendar.add(Calendar.DAY_OF_YEAR, 15);
        violation.setViolationDeadline(calendar.getTime());*/
        // 修改只能修改违章地点和说明
        ViolationEntity entity = new ViolationEntity();
        entity.setId(violation.getId());
        entity.setViolationAddress(violation.getViolationAddress());
        entity.setDescription(violation.getDescription());
        violationService.updateById(entity);
        return R.ok();
    }

    /**
     * 删除
     */
    @SysLog("删除违章记录")
    @DeleteMapping("/delete")
    @RequiresPermissions("mvs:violation:delete")
    public R delete(@RequestBody Integer[] ids) {
        // 检查被删除违章记录下是否有罚单
        int count = ticketService.count(new LambdaQueryWrapper<TicketEntity>()
                .in(TicketEntity::getViolationId, Arrays.asList(ids)));
        if (count > 0) {
            return R.error("被删除违章记录下存在罚单，不能删除");
        }

        violationService.removeByIds(Arrays.asList(ids));
        return R.ok();
    }

    /**
     * 导出违章记录excel
     */
    @SysLog("导出违章记录")
    @GetMapping("/export")
    @RequiresPermissions("mvs:violation:save")
    public void exportExcel(HttpServletResponse response) {
        try {
            // 设置响应头
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("违章记录", "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8'zh_cn'" + fileName + ".xlsx");

            // 准备数据
            HashMap<String, Object> map = new HashMap<>();
            map.put("page", "0");
            map.put("limit", "10");
            List<ViolationDto> list = (List<ViolationDto>) violationService.queryPage(map).getList();
            List<ViolationData> dataList = list.stream().map(violation -> {
                ViolationData violationData = new ViolationData();
                BeanUtils.copyProperties(violation, violationData);
                return violationData;
            }).collect(Collectors.toList());

            // 导出 Excel
            EasyExcel.write(response.getOutputStream(), ViolationData.class).sheet("违章记录").doWrite(dataList);
        } catch (IOException e) {
            log.error("违章记录导出失败：{}", e.getMessage());
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }

    /**
     * 导入excel
     */
    @SysLog("导入违章记录")
    @PostMapping("/import")
    @RequiresPermissions("mvs:violation:save")
    public R importExcel(@RequestParam("file") MultipartFile file) {
        try {
            ViolationDataListener listener = new ViolationDataListener(violationService);
            EasyExcel.read(file.getInputStream(), ViolationData.class, listener)
                    .sheet().doRead();
            List<Integer> errorRows = listener.getErrorRowIndexList();
            String msg = "成功导入" + listener.getViolationDataMap().size() + "条数据";
            if (!errorRows.isEmpty()) {
                msg += ", 第" + StringUtils.join(errorRows, ",") + "行数据导入失败";
            }
            return R.ok(msg);
        } catch (Exception e) {
            log.error("Excel导入失败：{}", e.getMessage());
            return R.error("系统错误，请联系管理员");
        }
    }

    /**
     * 获取指定用户的不在罚单里并且状态为未处理的违章记录id集合
     */
    @GetMapping("/list/id")
    @RequiresPermissions("mvs:violation:list")
    public R idListByUserId(@RequestParam(defaultValue = "0") Long userId) {
        List<Long> idList = violationService.getIdListByUserId(userId);
        return R.ok().put("violationIdList", idList);
    }

    /**
     * 获取指定日期范围内每日的违章次数
     */
    @GetMapping("/list/number")
//    @RequiresPermissions("mvs:violation:list")
    public R numberListByDateRange(@RequestParam(required = false) String startDate, @RequestParam(required = false) String endDate) {
        Map<String, Collection<?>> dataMap = violationService.getNumberListByDateRange(startDate, endDate);
        return R.ok().put("dataMap", dataMap);
    }
}
